上一回,我們已經完成意圖和景點資料的向量資料庫建立。今天,我們將進一步實作意圖執行的函式,讓系統能夠根據使用者的輸入,提供相應的旅遊資訊。
主要的意圖執行邏輯,該函式會使用 Azure OpenAI 生成文字嵌入,並透過 ChromaDB 來查詢景點的相關資料:
# chatbot_intents_function.py
import chromadb
from openai import AzureOpenAI
from openai_config import *
import json
# 初始化 ChromaDB 客戶端
chroma_client = chromadb.PersistentClient(path="./data/cut")
collection_name = "taipei_tourism"
collection = chroma_client.get_collection(name=collection_name)
# 初始化 Azure OpenAI 客戶端
client = AzureOpenAI(
azure_endpoint=azure_endpoint,
api_key=api_key,
api_version=api_version
)
# 生成嵌入向量
def get_embedding(text):
response = client.embeddings.create(
input=text,
model="text-embedding-3-large"
)
return response.data[0].embedding
# 查詢景點資訊
def get_attraction_info(parameters, entity):
# 生成景點名稱的嵌入向量
embedding = get_embedding(entity)
result = collection.query(query_embeddings=[embedding], n_results=1)
if not result['documents']:
return False, f"抱歉,找不到關於 {entity} 的資訊。"
# 將查詢結果中的 JSON 字符串轉為 Python 字典
json_text = result['documents'][0][0]
json_data = json.loads(json_text)
# 根據意圖參數處理結果
info = ""
found = True
if "介紹" in parameters:
intro = json_data.get('介紹', '暫無介紹資料')
info += f"{entity}的介紹:{intro}\n"
if "交通" in parameters:
transport = json_data.get('交通', '暫無交通資訊')
info += f"{entity}的交通資訊:{transport}\n"
if "地址" in parameters:
address = json_data.get('地址', '暫無地址資訊')
info += f"{entity}的地址是:{address}\n"
if "營業時間" in parameters:
hours = json_data.get('營業時間', '暫無營業時間資訊')
info += f"{entity}的營業時間是:{hours}\n"
if "照片" in parameters:
photo_url = json_data.get('照片', '暫無照片')
info += f"{entity}的照片:{photo_url}\n"
if not info:
found = False
info = "未找到符合條件的相關資訊,請提供更多具體內容。"
return found, info
# 意圖分析函數
def detect_intent(user_input):
if "介紹" in user_input or "景點" in user_input:
return "景點介紹"
elif "交通" in user_input or "怎麼去" in user_input:
return "交通資訊"
elif "地址" in user_input或 "位置" in user_input:
return "景點地址"
elif "營業時間" in user_input或 "開放時間" in user_input:
return "營業時間"
elif "照片" in user_input或 "圖片" in user_input:
return "景點照片"
else:
return "未知意圖"
# 根據使用者輸入提供資訊
def provide_info(user_input, collection):
intent = detect_intent(user_input)
place_name = user_input.split()[0] # 假設景點名稱為輸入的第一個詞
# 根據意圖設定查詢參數
parameters = []
if intent == "景點介紹":
parameters.append("介紹")
elif intent == "交通資訊":
parameters.append("交通")
elif intent == "景點地址":
parameters.append("地址")
elif intent == "營業時間":
parameters.append("營業時間")
elif intent == "景點照片":
parameters.append("照片")
else:
return "抱歉,我無法理解您的請求,請您再具體說明。"
# 調用查詢函數
found, response = get_attraction_info(parameters, place_name)
return response
意圖執行功能整合進 FastAPI 框架,並通過 WebSocket 實現即時互動:
from fastapi import FastAPI, WebSocket
from chatbot_intents_function import get_attraction_info, get_embedding, provide_info
from chromadb import PersistentClient
from openai import AzureOpenAI
from openai_config import *
# 初始化 FastAPI
app = FastAPI()
# 初始化 ChromaDB 客戶端和 collection
chroma_client = PersistentClient(path="./data/cut")
collection_name_intents = "taipei_tourist_intents"
intents_collection = chroma_client.get_collection(name=collection_name_intents)
collection_name_tourism = "taipei_tourism"
tourism_collection = chroma_client.get_collection(name=collection_name_tourism)
# 初始化 Azure OpenAI 客戶端
client = AzureOpenAI(
azure_endpoint=azure_endpoint,
api_key=api_key,
api_version=api_version
)
# 意圖識別函數
def detect_intent(user_input):
user_input_embedding = get_embedding(user_input)
result = intents_collection.query(
query_embeddings=[user_input_embedding], n_results=1
)
if not result["documents"]:
return None, "未能識別意圖。"
# 取得意圖和相應的執行動作
intents = result["documents"][0][0]
action = result["metadatas"][0][0]["function"]
return intents, action
# 處理使用者輸入
def process_user_input(user_input):
intents, action = detect_intent(user_input)
if not intents:
return action # 返回錯誤訊息
# 提供景點資訊
if action == "provide_info":
response = provide_info(user_input, tourism_collection)
return response
return "請輸入其他詳細資訊"
@app.websocket("/tourism/chatbot")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
try:
while True:
# 接收來自前端的訊息
user_input = await websocket.receive_text()
print("user_input", user_input)
# 處理使用者輸入
response = process_user_input(user_input)
print("response", response)
# 將回應訊息發送至前端
await websocket.send_text(response)
except Exception as e:
print(f"WebSocket connection closed with exception: {e}")
將意圖解析和景點資料查詢的邏輯結合在一起,使用 Azure OpenAI 生成嵌入向量並透過 ChromaDB 查詢資料庫的相似度,再透過 FastAPI 和 WebSocket 的結合,實現即時互動,讓用戶可以在旅遊過程中方便地查詢景點資訊。